package jarvis.fs;

import jarvis.fs.document.DocumentVector;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.store.Directory;

/**
 * 
 * Function: The Term Strength measure to get feature terms
 * @author Jarvis.Guo
 *
 */
public class TS extends FeatureSelection {


	/**
	 * the similary doc list which tell us the pairs 
	 * they are similar,values like [[1,2][1,3][2,4][3,5]]
	 * the number is refer to the docNum of index model,
	 * sorted
	 */
	private List<int[]> similaryList;
	
	//private DocumentVector[] documentsVector;
	
	/**
	 * @param dir
	 */
	public TS(Directory dir) {
		super(dir);
		similaryList = null;
	}

	/* (non-Javadoc)
	 * @see jarvis.fs.FeatureSelection#getTopNFeature(int)
	 */
	@Override
	public List<ComparableTerm> getFeatures() {
		List<ComparableTerm> result = new ArrayList<ComparableTerm>();
		//the similarity list like [[0,1],[0,2],[2,3]...]
		List<int[]> simList = getSimilaryList();
		int[] freqs = new int[simList.size()];
		//record the term freq in the sim pair that has values[0,1,2] which 2 means appear in both similar docs
		int i;
		for(i=0;i<freqs.length;i++) freqs[i] = 0;//init
		
		try{
			TermEnum te = indexReader.terms();
			TermDocs td = null;
			
			while(te.next())
			{
				Term term = te.term();
				td = indexReader.termDocs(term);
				while(td.next())
				{
					int doc = td.doc();//the term appears in doc
					i = 0;
					for(int[] sim:simList)
					{
						//if the terms appears in the simList[i]
						if(sim[0]==doc||sim[1]==doc)
						{
							//the frequence that the term appears in the simList[i] add 1
							freqs[i]++;//the value is in the range of [0,2]
						}
						i++;
					}
				}
				int appearBothly = 0;// term appears bothly in any similarity pair
				int appear = 0;
				for(i=0;i<freqs.length;i++)
				{
					int freq = freqs[i];
					if(freq==2) appearBothly++;
					appear += freq;
					freqs[i] = 0;//clear
				}
				if(appear!=0 && appearBothly!=0)
				{
					//To the condtional probability,
					//the value can computed by (appearBothly/length)/(appear/(length*2))
					//= 2*appearBothly/appear
					double value = (double)appearBothly*2/appear;
					result.add(new DoubleComparableTerm(term,value));
				}
				
			}
		}
		catch(IOException ex)
		{
			ex.printStackTrace();
			throw new RuntimeException(ex);
		}
		
		return result;
	}
	
	/**
	 * Get the similarity list, values like [[1,2][1,3][2,4][3,5]]
	 * @return
	 */
	public List<int[]> getSimilaryList()
	{
		//has been computed
		if(similaryList!=null) return similaryList;
		//compute it
		similaryList = new ArrayList<int[]>();
		
		DocumentVector[] vectors = DocumentVector.getVectors(indexReader);
		for(int i=0;i<vectors.length;i++)
		{
			for(int j=i+1;j<vectors.length;j++)
			{
				double sim = vectors[i].similary(vectors[j]);
				//System.out.println(i+","+j+":"+sim);
				if(sim>0.1)//factor
				{
					similaryList.add(new int[]{i,j});
				}
			}
		}
		
		
		return similaryList;
	}
	


}
